﻿#pragma once
namespace LK
{
	namespace Collection
	{
		/**
		@brief 表示一个固定最大大小的数组对象代理*/
		template<class T, index_t MaxSize>struct PFixedArray :PArray<T>
		{
			typedef FixedArray<T, MaxSize> vFixedArray;
			PMETHODS(PFixedArray, vFixedArray);
		};
		/**
		@brief 表示一个固定最大大小的数组对象*/
		template<class T, index_t MaxSize>struct FixedArray :virtual IArray<T>
		{
			typedef PFixedArray<T, MaxSize> xFixedArray;
			BMETHODS(xFixedArray, FixedArray)
			/**
			@brief 返回一个浅表副本*/
			FixedArray* Clone()const { return new FixedArray(*this); }
			/**
			@brief 当前元素数量*/
			index_t Length;
			/**
			@brief 获取元素数*/
			index_t size()const { return Length; }
			/**
			@brief 长度检查，len为负或越上限都抛出异常*/
			static void CheckLength(index_t len) { if (len<0)throw PInvalidArgumentException(L"数组长度不可以为负值"); if (len > MaxSize)throw PIndexOutOfRangeException(L"数组长度越上限"); }
			/**
			@brief 长度限制，len为负将抛出异常*/
			static index_t LimitLength(index_t len) { if (len < 0)throw PInvalidArgumentException(L"数组长度不可以为负值"); return len>MaxSize ? MaxSize : len; }
			/**
			@brief 获取数组当前最大容量
			@note 当数组元素数不大于最大容量，而且两者之差不大于MaxUnusedLength时，对象存储区域将不会进行内存的重新调整*/
			index_t GetMaxSize()const { return MaxSize; }
			/*
			@brief 数据记录器区*/
			u8 data[sizeof(T)*MaxSize];
			/**
			@brief 获取数组内容首地址*/
			virtual void const* GetData()const { return data; }
			/**
			@brief 调整大小，返回调整后数组元素最大大小
			@note 如果len>MaxSize或者len<0都将抛出异常*/
			virtual index_t Resize(index_t len)
			{
				CheckLength(len);
				if (len > Length) { IArrays::DefaultConstruct<T>(IArray<T>::getdata() + Length, len - Length); }
				else if (len < Length) { IArrays::Deconstruct<T>(IArray<T>::getdata() + len, Length - len); }
				Length = len;
				return MaxSize;
			}
			/**
			@brief 默认构造函数，构造一个空数组*/
			FixedArray() { Length = 0; }
			/**
			@brief 传入数组长度，构造一个未初始化的数组
			@note 当指定数组长度length大于MaxSize或小于0时，将抛出异常*/
			FixedArray(index_t length) { CheckLength(Length = length); IArrays::DefaultConstruct(IArray<T>::getdata(), length); }
#ifdef _INITIALIZER_LIST_//初始化列表支持
			FixedArray(std::initializer_list<T> const& lst) : Length(0), data(NULL)
			{
				for (auto const&a : lst)IArray::Append(a);
			}
#endif
			/**
			@brief 复制构造函数
			@note 新数组的类型将是FixedArray，另外，如果传入数组的元素数大于MaxSize，则取前MaxSize个元素来构造*/
			FixedArray(const IArray<T>&vfa) { Length = LimitLength(vfa.Length); IArrays::Construct(IArray<T>::getdata(), vfa.IArray<T>::getdata(), Length); }
			/**
			@brief 复制构造函数
			@note 新数组的类型将是FixedArray，另外，如果传入数组的元素数大于MaxSize，则取前MaxSize个元素来构造*/
			FixedArray(const FixedArray&vfa) { Length = LimitLength(vfa.Length); IArrays::Construct(IArray<T>::getdata(), vfa.IArray<T>::getdata(), Length); }
			/**
			@brief 复制构造函数
			@note 新数组的类型将是FixedArray，另外，如果传入数组的元素数大于MaxSize，则取前MaxSize个元素来构造*/
			FixedArray&operator=(const FixedArray&vfa)
			{
				Resize(LimitLength(vfa.Length));
				T*p = IArray<T>::getdata();
				T*pp = vfa.IArray<T>::getdata();
				for (index_t i = 0; i < Length; ++i)p[i] = pp[i];
				return *this;
			}
			/**
			@brief 传入数组元素，并使用一个参考元素来初始化所有元素
			@param [传入]参数len表示数组元素数
			@param [传入]参数t为参考元素
			@note 当指定数组长度len大于MaxSize或小于0时，将抛出异常*/
			FixedArray(index_t len, const T&t) { CheckLength(Length = len); IArrays::ConstructWith(IArray<T>::getdata(), t, len); }
			/**
			@brief 使用迭代器构造，如果迭代器所表示内容多于MaxSize，则只取前MaxSize个内容来构造*/
			template<class IT>FixedArray(const IT&first, const IT&end, typename UseIf<IsConvertible<typename IT::value_type, T>::V>::T*p = NULL)
			{
				Length = 0; IT it = first; while (it != end) { if (Length == MaxSize)break; IArray<T>::template Append<typename IT::value_type>(*it); ++it; }
			}
			/**
			@brief 直接传入元素数和指针来构造数组
			@param [传入]参数len用以指定元素数
			@param [传入]参数p指向存放空间
			@note 若len<0或len>MaxSize将抛出异常，如果p为NULL进行默认初始化*/
			FixedArray(index_t len, const T*p) { CheckLength(Length = len); if (p)IArrays::Construct(IArray<T>::getdata(), p, len); else IArrays::DefaultConstruct(IArray<T>::getdata(), len); }
			/**
			@brief 从C-Style数组复制构造*/
			template<class TT>FixedArray(const TT&arr, typename UseIf<IsArray<TT>::V>::T*p = NULL) { CheckLength(Length = IsArray<TT>::C); if (p)IArrays::Construct(IArray<T>::getdata(), arr, Length); }
			/**
			@brief 析构函数*/
			~FixedArray() { Resize(0); }
		};

#define _T_CASE(x)\
 case x:\
	{\
	return new  FixedArray<T,(((size_t)1<<x)-sizeof(size_t)*3-sizeof(Collection::FixedArray<u8,sizeof(size_t)>))/sizeof(T)>();\
}
		template<class T>IArray<T>* MakeFixedArray(index_t size)
		{
			switch (sizeof(size_t) * 8 - Bits::LeftZeroCount(size*sizeof(T) + sizeof(Collection::FixedArray<u8, sizeof(size_t)>) + sizeof(size_t) * 3))
			{
			default:
				MF3_RepeatAsc(_T_CASE, 8, 30)
			}
		}
#undef _T_CASE
	}

}